/**
@author		Jong Min, Lee
@date		  10/01/2014
@breif		series class and producer class 

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#include "stdafx.h"
#include "Taurus_DcmData/Series.h"
#include "Taurus_Util/Errors.h"
#include "Taurus_DcmData/Study.h"
#include "Taurus_DcmData/DcmSeries.h"
#include "Taurus_DcmData/DcmInstance.h"
#include "Taurus_DcmData/Instance.h"

CSeries::CSeries()
{
  init();
}

CSeries::~CSeries()
{
  destroy();
}

const TCHAR* CSeries::getModality() const
{
  return m_theDcmSeries->getModality();
}

BOOL CSeries::isNoneImage() const
{
  BOOL isNoneImage = FALSE;
  CString modality = getModality();

  if(modality == _T("PR") || modality == _T("SR"))
  {
    isNoneImage = FALSE;
  }
  else if(modality.Find(_T("SR")))
  {
    isNoneImage = FALSE;
    unsigned int num = m_theInstances.size();
    for(unsigned int i = 0; i < num; ++i)
    {
      const TCHAR* pszSOPClassUID = m_theInstances[i]->getSOPClassUID();
      if((_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.4.2")) == 0)    ||   //Spectroscopy
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.11")) == 0)  ||   //basic text SR
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.22")) == 0)  ||   //Enhanced SR
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.33")) == 0)  ||   //Comprehensive SR
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.50")) == 0)  ||   //Mammography CAD SR
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.65")) == 0)  ||   //Chest CAD SR
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.88.59")) == 0)    )  //Key object selection DOC
      {
        isNoneImage = TRUE;
        break;
      }
    }
  }//else if(m_strModality.Find(_T("SR"))
  else if(modality == _T("ECG"))
  {
    isNoneImage = FALSE;
    unsigned int num = m_theInstances.size();
    for(unsigned int i = 0; i < num; ++i)
    {
      const TCHAR* pszSOPClassUID = m_theInstances[i]->getSOPClassUID();
      if((_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.9.1.1")) == 0) || //12-lead
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.9.2.1")) == 0) || //HemodynamicWaveformStorage
        (_tcscmp(pszSOPClassUID, _T("1.2.840.10008.5.1.4.1.1.9.1.2")) == 0)  ) //General ECG Waveform Storage
      {
        isNoneImage = TRUE;
        break;
      }
    }
  }
  // TODO(Jong Min, Lee): compare modality with "MG" and check image size

  return isNoneImage;
}

const CInstance* CSeries::getInstance(const unsigned int index) const
{
  if(index >= m_theInstances.size()) NULL;

  return m_theInstances[index];
}

CInstance* CSeries::getInstance(const unsigned int index)
{
  if(index >= m_theInstances.size()) NULL;

  return m_theInstances[index];
}

void CSeries::init()
{
  m_theParent = NULL;
  m_theDcmSeries = NULL;
}

void CSeries::destroy()
{
  m_theDcmSeries->decreaseRefCount();

  removeAllInstances();
}

void CSeries::removeAllInstances()
{
  unsigned int num = m_theInstances.size();
  for(unsigned int i = 0; i < num; ++i)
    _DELETE(m_theInstances[i])
  m_theInstances.clear();
}

DWORD CSeriesProducer::produce(CDcmSeries* dcmSeries, CStudy* parent, CSeries*& outSeries)
{
  if(dcmSeries == NULL) return ERROR_INVALID_PARAMETER;

  CSeries* newSeries = NULL;
  _TRY_ALLOC(newSeries, CSeries)
  if(newSeries == NULL) return ERROR_NOT_ENOUGH_MEMORY;

  DWORD error = attachDcmSeries(newSeries, dcmSeries, parent);
  if(error != ERROR_SUCCESS)
  {
    _DELETE(newSeries)
    return error;
  }

  unsigned int numInstance = dcmSeries->getNumInstances();
  if(numInstance == 0)
  {
    _DELETE(newSeries)
    return ERROR_INVALID_SERIES_INFO;
  }

  _TRY_BEGIN
  newSeries->m_theInstances.reserve(numInstance);
  _CATCH_ALL
  _DELETE(newSeries);
  return ERROR_NOT_ENOUGH_MEMORY;
  _CATCH_END

  for(unsigned int i = 0; i < numInstance; ++i)
  {
    CDcmInstance* dcmInstance = dcmSeries->getInstance(i);
    if(dcmInstance == NULL) continue;

    CInstance* newInstance = NULL;
    error = CInstanceProducer::produce(dcmInstance, newSeries, newInstance);
    if(error != ERROR_SUCCESS)
    {
      _DELETE(newSeries)
      return error;
    }

    newSeries->m_theInstances.push_back(newInstance);
  }

  if(newSeries->m_theInstances.size() == 0)
  {
    _DELETE(newSeries);
    return ERROR_INVALID_SERIES_INFO;
  }

  outSeries = newSeries;
  return ERROR_SUCCESS;
}

DWORD CSeriesProducer::produce(CDcmSeries* dcmSeries, 
                               CInstance** instances, 
                               const unsigned int numInstances, 
                               CStudy* parent, 
                               CSeries*& outSeries)
{
  if(dcmSeries == NULL) return ERROR_INVALID_PARAMETER;

  if(instances == NULL && numInstances > 0)  return ERROR_INVALID_PARAMETER;

  if(numInstances == 0) return ERROR_INVALID_PARAMETER;

  CSeries* newSeries = NULL;
  _TRY_ALLOC(newSeries, CSeries)
  if(newSeries == NULL) return ERROR_NOT_ENOUGH_MEMORY;

  DWORD error = attachDcmSeries(newSeries, dcmSeries, parent);
  if(error != ERROR_SUCCESS)
  {
    _DELETE(newSeries)
    return error;
  }

  try
  {
    newSeries->m_theInstances.reserve(numInstances);
  }
  catch(...)
  {
    _DELETE(newSeries);
    return ERROR_NOT_ENOUGH_MEMORY;
  }

  for(unsigned int i = 0; i < numInstances; ++i)
  {
    newSeries->m_theInstances.push_back(instances[i]);
    instances[i]->setParent(newSeries);
  }

  if(newSeries->m_theInstances.size() == 0)
  {
    _DELETE(newSeries)
    return ERROR_INVALID_SERIES_INFO;
  }

  outSeries = newSeries;
  return ERROR_SUCCESS;
}

DWORD CSeriesProducer::attachDcmSeries(CSeries* series, CDcmSeries* dcmSeries, CStudy* parent)
{
  if(series == NULL || dcmSeries == NULL) return ERROR_INVALID_PARAMETER;

  series->m_theDcmSeries = dcmSeries;
  series->m_theDcmSeries->increaseRefCount();
  series->m_theParent = parent;

  return ERROR_SUCCESS;
}
